package com.oracle.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.oracle.pojo.Admin;
import com.oracle.pojo.LoginForm;
import com.oracle.pojo.Student;
import com.oracle.pojo.Teacher;
import com.oracle.service.IAdminService;
import com.oracle.service.IStudentService;
import com.oracle.service.ITeacherService;
import com.oracle.util.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;


@Api(tags = "系统管理器")
@RestController
@RequestMapping("/sms/system")
public class SystemController {
    @Autowired
    private IAdminService adminService;
    @Autowired
    private IStudentService studentService;
    @Autowired
    private ITeacherService teacherService;


    /**
     * 跳转至首页功能
     * 通过请求头中的Token字符串解析出用户输入信息的用户类型和用户Id，然后按照id从数据库中查询用户，最终返回给前台一个json字符串
     *
     * login响应结果
     *  {
     *      "code":200,
     *      "message":"成功",
     *      "data":{
     *          "token":"gwrgwrgwrihwr guw9e[weewpgweighwgjw gwigwgw",
     *      }
     *      "ok":"true"
     *  }
     *
     *  getInfo响应结果
     *  {
     *      "code":200,
            "message":"成功",
     *      "data":{
     *          "user":{
     *              "id":"1",
     *              "name":"admin",
     *              "gender":1,
     *              ....
     *          }
     *          "userType":"1"
     *      },
     *      "ok":"true"
     *  }
     *
     *
     *
     */
    @ApiOperation("跳转至首页功能")
    @GetMapping("/getInfo")
    public Result getUserInfoByToken(
            @ApiParam("用户登录后存储在session域对象中的token字符串") @RequestHeader("token")String token){
        // 使用请求头中的token，通过JwtHelper类判断当前token是否过期，如果过期了，就返回一个信息---token已失效
        boolean expiration = JwtHelper.isExpiration(token);
        if(expiration){
            // 失效，则返回枚举类中的TOKEN_ERROR，Result对象的body为null即可
            return Result.build(null, ResultCodeEnum.TOKEN_ERROR);
        }
        // token没有失效，则通过其获取登录用户的信息
        // 获取用户的id
        Long userId = JwtHelper.getUserId(token);
        // 获取用户的类型
        Integer userType = JwtHelper.getUserType(token);

        Map<String,Object> map = new LinkedHashMap<>();
        /**
         * 通过用户的类型，分别返回三种对象
         */
        switch (userType){
            case 1:
                Admin admin = adminService.getAdminById(userId);
                map.put("user",admin);
                map.put("userType",1);
                break;
            case 2:
                Student student = studentService.getStudentById(userId);
                map.put("user",student);
                map.put("userType",2);
                break;
            case 3:
                Teacher teacher = teacherService.getTeacherById(userId);
                map.put("user",teacher);
                map.put("userType",3);
                break;
        }
        return Result.ok(map);
    }


    /**
     * 登录校验
     */
    @ApiOperation("登录验证功能")
    @PostMapping("/login")
    public Result login(
           @ApiParam("登录页面信息封装的对象") @RequestBody LoginForm loginForm,
           @ApiParam("Request请求对象") HttpServletRequest request){
        /**
         * 验证码校验
         */
        HttpSession session = request.getSession();
        // 获取session域对象中的验证码
        String sessionVerifiCode = (String) session.getAttribute("verifiCode");
        // 获取当前登录页面用户在验证码输入框中输入的验证码
        String loginVerifiCode1 = loginForm.getVerifiCode();
        // 判断从session域对象中获取的验证码是否为空，为空则代表已经过期
        if("".equals(sessionVerifiCode) || null == sessionVerifiCode){
            return  Result.fail().message("验证码失效，请刷新后重试....");
        }
        // 判断用户输入的验证码和从session域对象中获取的验证码（session域对象中的获取的验证码就是获取验证码方法获取之后存放在域对象中的）是否匹配
        if(!sessionVerifiCode.equalsIgnoreCase(loginVerifiCode1)){
            return Result.fail().message("验证码有误,请小心输入后重试...");
        }
        // 不管是否匹配，都要在每次登录页面刷新的时候保存在域对象中的验证码的值删除，
        // 不然会造成验证码不是最新的的情况，这样就不能实现每次登录页面刷新时都获取最新的验证码图片

        // 从session域中移除当前验证码
        session.removeAttribute("verifiCode");

        /**
         * 用户类型校验  管理员、学生、教师
         */
        // 定义一个集合用于存储响应信息
        Map<String,Object> map = new LinkedHashMap<>();
        switch (loginForm.getUserType()){
//            管理员
            case 1:
                try {
                    // 通过service的登录方法获取admin对象
                    Admin admin =  adminService.login(loginForm);
                    if (admin != null) {
                        // 登录成功，将用户id和用户的类型转换为token密令，作为信息响应给前端
                        map.put("token", JwtHelper.createToken(admin.getId().longValue(),1));
                    }else{
                        // 登录失败，抛出异常，提示信息
                        throw new RuntimeException("用户名或密码有误");
                    }
                    // 登录成功后返回浏览器一个标准对象Result
                    return  Result.ok(map);
                } catch (RuntimeException e) {
                    e.printStackTrace();
                    // 登录失败，返回Result对象
                    return Result.fail().message(e.getMessage());
                }
//                学生
            case 2:
                try {
                    // 通过service的登录方法获取admin对象
                    Student student =  studentService.login(loginForm);
                    if (student != null) {
                        // 登录成功，将用户id和用户的类型转换为token密令，作为信息响应给前端
                        map.put("token", JwtHelper.createToken(student.getId(),2));
                    }else{
                        // 登录失败，抛出异常，提示信息
                        throw new RuntimeException("用户名或密码有误");
                    }
                    // 登录成功后返回浏览器一个标准对象Result
                    return  Result.ok(map);
                } catch (RuntimeException e) {
                    e.printStackTrace();
                    // 登录失败，返回Result对象
                    return Result.fail().message(e.getMessage());
                }
//                  教师
            case 3:
                try {
                    // 通过service的登录方法获取admin对象
                    Teacher teacher =  teacherService.login(loginForm);
                    if (teacher != null) {
                        // 登录成功，将用户id和用户的类型转换为token密令，作为信息响应给前端
                        map.put("token", JwtHelper.createToken(teacher.getId(),3));
                    }else{
                        // 登录失败，抛出异常，提示信息
                        throw new RuntimeException("用户名或密码有误");
                    }
                    // 登录成功后返回浏览器一个标准对象Result
                    return  Result.ok(map);
                } catch (RuntimeException e) {
                    e.printStackTrace();
                    // 登录失败，返回Result对象
                    return Result.fail().message(e.getMessage());
                }
        }
        // 如果不是管理员、学生、教师表中的数据，表示查无此用户
        return  Result.fail().message("查无此用户");
    }


    /**
     * 获取验证码图片
     * @param request
     * @param response
     */
    @ApiOperation("获取登录页面生成的验证码信息")
    @GetMapping("/getVerifiCodeImage")
    public void getVerifiCodeImage(
            @ApiParam("Request请求对象") HttpServletRequest request,
            @ApiParam("Response响应对象") HttpServletResponse response)  {
        // 获取图片
        BufferedImage verifiCodeImage = CreateVerifiCodeImage.getVerifiCodeImage();
        // 获取图片验证码
        String verifiCode = new String(CreateVerifiCodeImage.getVerifiCode());
        // 将验证码文本放入session域，为下一次验证做准备
        HttpSession session = request.getSession();
        session.setAttribute("verifiCode",verifiCode);
        // 将验证码图片响应给浏览器
//        ServletOutputStream outputStream = response.getOutputStream();
        try {
            ImageIO.write(verifiCodeImage,"JPEG",response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 头像上传操作
     * http://localhost/sms/system/headerImgUpload
     */
    @PostMapping("/headerImgUpload")
    @ApiOperation("用户头像上传功能")
    public Result headImageUpload(
            @ApiParam("上传的头像文件") @RequestPart("multipartFile") MultipartFile multipartFile
    ){
        /**
         * 使用UUID类的randomUUID()方法生成上传的图片的名称
         */
        String randomName = UUID.randomUUID().toString().replace("-", "").toLowerCase();
        /**
         * 拼接新的文件名称
          */
        // 获取文件的原始名称
        String originalFilename = multipartFile.getOriginalFilename();
        // 获取文件的后缀名
        int index = originalFilename.lastIndexOf(".");
        // 截取原始文件名获取图片后缀名
        String suffixName = originalFilename.substring(index);
        // 生成新的文件名
        String newFileName = randomName.concat(suffixName);
        // 设置文件的保存路径
        String portraitPath = "D:/WorkSpace/SpringBoot/wisdom-campus/target/classes/public/upload/".concat(newFileName);
        // 执行保存操作
        try {
            multipartFile.transferTo(new File(portraitPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 返回给前台浏览器一个文件的全路径名
        String headerImage = "upload/"+newFileName;

        return Result.ok(headerImage);
    }
    /**
     * 用户修改密码操作
     * 请求参数：  oldPwd  旧密码
     *            newPwd   新密码
     *            token，用于校验用户类型
     */
    @PostMapping("/updatePwd/{oldPwd}/{newPwd}")
    @ApiOperation("用户修改密码功能")
    public Result updateUserPwd(
            @ApiParam("请求参数中的Token对象") @RequestHeader String token,
            @ApiParam("用户的修改前的密码") @PathVariable("oldPwd") String oldPwd,
            @ApiParam("用户的修改后的密码") @PathVariable("newPwd") String newPwd
    ){
        // 通过工具类JwtHelper,将请求参数中的token放入方法参数中，判断token是否过期
        boolean expiration = JwtHelper.isExpiration(token);
        if(expiration){
            return Result.fail().message("token失效！");
        }else{
            // 通过token获取当前登录用户的id和用户类型
            Long userId = JwtHelper.getUserId(token);
            Integer userType = JwtHelper.getUserType(token);
            // 将密码加密
            oldPwd = MD5.encrypt(oldPwd);
            newPwd = MD5.encrypt(newPwd);
            switch (userType){
                case 1:
                    QueryWrapper<Admin> adminQueryWrapper = new QueryWrapper<>();
                    adminQueryWrapper.eq("id",userId.intValue());
                    if (!StringUtils.isEmpty(oldPwd)){
                        adminQueryWrapper.eq("password",oldPwd);
                    }
                    Admin admin = adminService.getOne(adminQueryWrapper);
                    if(admin!=null){
                        // 执行修改密码操作
                        admin.setPassword(newPwd);
                        adminService.saveOrUpdate(admin);
                    }else{
                        return Result.fail().message("原密码输入有误！");
                    }
                    break;
                case 2:
                    QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
                    studentQueryWrapper.eq("id",userId.intValue());
                    if (!StringUtils.isEmpty(oldPwd)){
                        studentQueryWrapper.eq("password",oldPwd);
                    }
                    Student student = studentService.getOne(studentQueryWrapper);
                    if(student!=null){
                        // 执行修改密码操作
                        student.setPassword(newPwd);
                        studentService.saveOrUpdate(student);
                    }else{
                        return Result.fail().message("原密码输入有误！");
                    }
                    break;
                case 3:
                    QueryWrapper<Teacher> teacherQueryWrapper = new QueryWrapper<>();
                    teacherQueryWrapper.eq("id",userId.intValue());
                    if (!StringUtils.isEmpty(oldPwd)){
                        teacherQueryWrapper.eq("password",oldPwd);
                    }
                    Teacher teacher = teacherService.getOne(teacherQueryWrapper);
                    if(teacher!=null){
                        // 执行修改密码操作
                        teacher.setPassword(newPwd);
                        teacherService.saveOrUpdate(teacher);
                    }else{
                        return Result.fail().message("原密码输入有误！");
                    }
                    break;
            }
        }
        return Result.ok();
    }

}
